package com.hundun.vision.biz.core;

import org.apache.commons.lang3.StringUtils;
import org.ta4j.core.BarSeries;
import org.ta4j.core.BaseStrategy;
import org.ta4j.core.Rule;
import org.ta4j.core.Strategy;
import org.ta4j.core.indicators.SMAIndicator;
import org.ta4j.core.indicators.bollinger.BollingerBandsLowerIndicator;
import org.ta4j.core.indicators.bollinger.BollingerBandsMiddleIndicator;
import org.ta4j.core.indicators.bollinger.BollingerBandsUpperIndicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;
import org.ta4j.core.indicators.statistics.StandardDeviationIndicator;
import org.ta4j.core.num.DecimalNum;
import org.ta4j.core.rules.CrossedDownIndicatorRule;
import org.ta4j.core.rules.CrossedUpIndicatorRule;
import org.ta4j.core.rules.StopLossRule;

import java.math.BigDecimal;

import static java.math.RoundingMode.DOWN;

/**
 * @author ：RuoChen
 * @date ：14:10 2024/2/27
 * @description：布林带多单策略
 */
public class BollingerBandBuyStrategy {
    private static final String name = "布林带多单策略";

    /**
     * 构建交易策略
     *
     * @param barSeries
     * @param stopLossPercentage
     * @param symbol
     * @param pricePrecision
     * @return
     */
    public static Strategy buildStrategy(BarSeries barSeries, BigDecimal stopLossPercentage, String symbol, Integer pricePrecision) {
        // 获取收盘价
        ClosePriceIndicator closePrice = new ClosePriceIndicator(barSeries);
        // 计算布林带
        int bbPeriod = 20;
        SMAIndicator sma = new SMAIndicator(closePrice, bbPeriod);
        StandardDeviationIndicator stdDev = new StandardDeviationIndicator(closePrice, bbPeriod);
        BollingerBandsMiddleIndicator middleBrand = new BollingerBandsMiddleIndicator(sma);
        // 计算布林带上下轨
        BollingerBandsUpperIndicator upperBand = new BollingerBandsUpperIndicator(middleBrand, stdDev);
        BollingerBandsLowerIndicator lowerBand = new BollingerBandsLowerIndicator(middleBrand, stdDev);

        if (StringUtils.isNotEmpty(symbol)) {
            BigDecimal upperPrice = upperBand.getValue(barSeries.getEndIndex()).bigDecimalValue().setScale(pricePrecision, DOWN);
            BigDecimal lowerPrice = lowerBand.getValue(barSeries.getEndIndex()).bigDecimalValue().setScale(pricePrecision, DOWN);
            BigDecimal price = barSeries.getBar(barSeries.getEndIndex()).getClosePrice().bigDecimalValue();
            BigDecimal lastPrice = barSeries.getBar(barSeries.getEndIndex() - 1).getClosePrice().bigDecimalValue();
            System.out.println("buy strategy symbol:" + symbol + "|price:" + price + "|last:" + lastPrice + "|lower:" + lowerPrice + "|upper:" + upperPrice);
        }

        // 当前价格上穿布林带下线：买入（多单建仓）
        Rule entryRule = new CrossedUpIndicatorRule(closePrice, lowerBand);
        // 当前价格下穿布林带上线：卖出（多单止盈）
        Rule takeProfitRule = new CrossedDownIndicatorRule(closePrice, upperBand);
        StopLossRule stopLossRule = new StopLossRule(closePrice, DecimalNum.valueOf(stopLossPercentage));
        Rule exitRule = takeProfitRule.or(stopLossRule);
        Strategy strategy = new BaseStrategy(name, entryRule, exitRule);
        return strategy;
    }
}
